package es.unileon.is.finalproyect.texts;

import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import es.unileon.is.finalproyect.auxiliar.Streams;
import es.unileon.is.finalproyect.dbconnection.*;
import es.unileon.is.finalproyect.exceptions.UniqueException;
import es.unileon.is.finalproyect.users.User;

public class Text {
	
	private int _id;
	private String _title;
	private byte _data[];
	private int _secondsToRead;
	private int _secondsToAnswer;
	
	private Text(int id){
		try {
			PreparedStatement ps = ApplicationConnection.getConnection().prepareStatement("SELECT title, dataFile, secondsToRead, secondsToAnswer FROM TEXTS WHERE textNumber = ?");
			ps.setInt(1, id);
			ResultSet rs = ps.executeQuery();
			if(rs.next()){
				_title= rs.getString(1);
				_data = Streams.inputStreamToByteArray(rs.getBlob(2).getBinaryStream());
				_secondsToRead = rs.getInt(3);
				_secondsToAnswer = rs.getInt(4);
				_id=id;
			} else {
				throw new RuntimeException("That text does not exist");
			}
		} catch (SQLException e) {
			throw new RuntimeException(e.getMessage());
		}
	}
	
	public Text(User admin, String title, byte[] data, int secondsToRead, int secondsToAnswer) throws UniqueException{
		if(!admin.isAdministrator()){
			throw new RuntimeException("You do not have enough privileges to perform this operation");
		}
		_title = title;
		_data = Arrays.copyOf(data, data.length);
		_secondsToRead = secondsToRead;
		_secondsToAnswer = secondsToAnswer;
		try {
			if(storeText()){
				PreparedStatement ps = ApplicationConnection.getConnection().prepareStatement("SELECT textNumber, dataFile FROM TEXTS WHERE title = ?");
				ps.setString(1, _title);
				ResultSet rs = ps.executeQuery();
				if(rs.next()){
					_id = rs.getInt(1);
				} else {
					throw new RuntimeException("The text has not been saved");
				}
			} else {
				//LANZAR UNA EXCEPCION
				throw new RuntimeException("The Text has not been saved");
			}
		} catch (SQLException e) {
			String msg = e.getMessage();
			if(msg.contains("UK_Texts")){
				throw new UniqueException("There is one texts with that name. Choose other one");
			}
			throw new RuntimeException(e.getMessage());
		}	
	}
	
	public Text(User admin, String title, InputStream data, int secondsToRead, int secondsToAnswer) throws UniqueException{
		this(admin, title, Streams.inputStreamToByteArray(data), secondsToRead, secondsToAnswer);
	}
	
	public List<Question> get10RandomQuestion(){
		List<Integer> numQuestion = new ArrayList<Integer>();
		List<Question> tenQuestion = new ArrayList<Question>();
		try {
			ResultSet rs = ApplicationConnection.getConnection().prepareStatement("SELECT questionNumber FROM QUESTIONS WHERE textNumber = "+_id).executeQuery();
			while(rs.next()){
				numQuestion.add(rs.getInt(1));
			}
		} catch (SQLException e) {
			throw new RuntimeException(e.getMessage());
		}
		int i=0;
		while(i<10){
			int longitud = numQuestion.size();
			int aleatorio = (int) (Math.random()*longitud);
			tenQuestion.add(Question.requestQuestion(_id, numQuestion.remove(aleatorio)));
			i++;			
		}
		return tenQuestion;
	}
	
	public byte[] getData(){
		return Arrays.copyOf(_data, _data.length);
	}

	public int getID(){
		return _id;
	}
	
	public String getTitle(){
		return _title;
	}
	
	private boolean storeText(){
		try {
			PreparedStatement ps = ApplicationConnection.getConnection().prepareStatement("INSERT INTO TEXTS (title, dataFile, secondsToRead, secondsToAnswer) VALUES (?,?,?,?)");
			ps.setString(1, _title);
			ps.setBinaryStream(2, Streams.byteArrayToInputStream(_data));
			ps.setInt(3, _secondsToRead);
			ps.setInt(4, _secondsToAnswer);
			ps.execute();
			return true;
		} catch (SQLException e) {
			throw new RuntimeException(e.getMessage());
		}
	}
	
	public boolean changeTitle(String title){
		try {
			ApplicationConnection.getConnection().prepareStatement("UPDATE TEXTS SET TITLE = '" + title + "' WHERE textNumber = " + _id).execute();
			_title = title;
			return true;
		} catch (SQLException e) {
			return false;
		}
	}
	
	public static List<Text> requestAllTexts(User admin){
		if(!admin.isAdministrator()){
			throw new RuntimeException("You do not have enough privileges to perform this operation");
		}
		List<Text> list = new ArrayList<Text>();
		try{
			ResultSet rs = ApplicationConnection.getConnection().prepareStatement("SELECT textNumber FROM TEXTS").executeQuery();
			while(rs.next()){
				list.add(Text.requestText(rs.getInt(1)));
			}
			return list;
		} catch (SQLException e){
			throw new RuntimeException(e.getMessage());
		}
	}
	
	public static Text requestText(int id){
		return new Text(id);
	}
	
	public float getGlobalAverage(){
		try{
			PreparedStatement ps = ApplicationConnection.getConnection().prepareStatement("SELECT mark FROM RESOLVED_TEXTS WHERE textNumber = ?");
			ps.setInt(1, _id);
			ResultSet rs = ps.executeQuery();
			int suma = 0;
			int cantidad = 0;
			while(rs.next()){
				suma += rs.getInt(1);
				cantidad++;
			}
			if(cantidad == 0){
				return 0.0f;
			} else {
				return (float) suma/cantidad;
			}
		} catch (SQLException e){
			throw new RuntimeException(e.getMessage());
		}
	}
	
	
	public int getSecondsToRead(){
		return _secondsToRead;
	}
	
	public boolean setSecondsToRead(User admin, int seconds){
		if(!admin.isAdministrator()){
			throw new RuntimeException("You do not have enough privileges to perform this operation");
		}
		if(seconds > 0){
			try{
				PreparedStatement ps = ApplicationConnection.getConnection().prepareStatement("UPDATE TEXTS SET secondsToRead = ? WHERE textNumber = ?");
				ps.setInt(1, seconds);
				ps.setInt(2, _id);
				ps.execute();
				_secondsToRead = seconds;
				return true;
			} catch (SQLException e){
				throw new RuntimeException(e.getMessage());
			}
		} else {
			return false;
		}
	}
	
	public int getSecondsToAnswer(){
		return _secondsToAnswer;
	}
	
	public boolean setSecondsToAnswer(User admin, int seconds){
		if(!admin.isAdministrator()){
			throw new RuntimeException("You do not have enough privileges to perform this operation");
		}
		if(seconds > 0){
			try{
				PreparedStatement ps = ApplicationConnection.getConnection().prepareStatement("UPDATE TEXTS SET secondsToAnswer = ? WHERE textNumber = ?");
				ps.setInt(1, seconds);
				ps.setInt(2, _id);
				ps.execute();
				_secondsToAnswer = seconds;
				return true;
			} catch (SQLException e){
				throw new RuntimeException(e.getMessage());
			}
		} else {
			return false;
		}
	}
	
	public void deleteText(User admin){
		if(!admin.isAdministrator()){
			throw new RuntimeException("You do not have enough privileges to perform this operation");
		}
		try{
			PreparedStatement ps = ApplicationConnection.getConnection().prepareStatement("DELETE FROM TEXTS WHERE textNumber = ?");
			ps.setInt(1, _id);
			ps.execute();
		} catch (SQLException e){
			throw new RuntimeException(e.getMessage());
		}
	}
	
}
